#include "RenderAPI.h"

#include "Core/GlobalContext.h"

#include "Platform/OpenGL/OpenGLAPI.h"

namespace SE
{
	Ref<RenderAPI> RenderAPI::Create(const RenderAPIType type)
	{
		switch (type)
		{
			default: SE_ASSERT(false, "Unkown render api type!"); return nullptr;
			case RenderAPIType::OpenGL: return CreateRef<OpenGLAPI>();
		}
	}

    RenderAPIType RenderAPI::GetAPIType()
    {
        return GlobalContext::GetRenderAPI()->getAPIType();
    }

    void RenderAPI::MakeContextCurrent(const Ref<RenderContext>& context)
    {
        GlobalContext::GetRenderAPI()->makeContextCurrent(context);
    }

    void RenderAPI::SetViewport(
        const U32 x,
        const U32 y,
        const U32 width,
        const U32 height)
    {
        GlobalContext::GetRenderAPI()->setViewport(x, y, width, height);
    }

    void RenderAPI::SetClearColor(const Vector4f& color)
    {
        GlobalContext::GetRenderAPI()->setClearColor(color);
    }

    void RenderAPI::SetLineWidth(const Float width)
    {
        GlobalContext::GetRenderAPI()->setLineWidth(width);
    }

    void RenderAPI::Clear()
    {
        GlobalContext::GetRenderAPI()->clear();
    }

    void RenderAPI::BindToBackground()
    {
        GlobalContext::GetRenderContext()->background->bind();
    }

    void RenderAPI::BindToForeground()
    {
        GlobalContext::GetRenderContext()->background->unbind();
    }

    Ref<FrameBuffer> RenderAPI::GetBackground()
    {
        return GlobalContext::GetRenderContext()->background;
    }

    Vector2i RenderAPI::GetBackgroundSize()
    {
        auto& background = GlobalContext::GetRenderContext()->background;
        return { background->getWidth(), background->getHeight() };
    }

    void RenderAPI::ResizeBackground(const U32 width, const U32 height)
    {
        GlobalContext::GetRenderContext()->background->setBuffer(width, height);
    }

    void RenderAPI::BeginScene(const CameraData cameraData)
    {
        GlobalContext::GetRenderAPI()->beginScene(cameraData);
    }

    void RenderAPI::EndScene()
    {
        GlobalContext::GetRenderAPI()->endScene();
    }

    void RenderAPI::StartBatch()
    {
        GlobalContext::GetRenderAPI()->startBatch();
    }

    void RenderAPI::NextBatch()
    {
        GlobalContext::GetRenderAPI()->nextBatch();
    }

    void RenderAPI::Flush()
    {
        GlobalContext::GetRenderAPI()->flush();
    }

    void RenderAPI::ResetStats()
    {
        GlobalContext::GetRenderAPI()->resetStats();
    }

    void RenderAPI::EnableTests(const EnabledTest enabledTests)
    {
        GlobalContext::GetRenderAPI()->enableTests(enabledTests);
    }

    void RenderAPI::DisableTests(const EnabledTest enabledTests)
    {
        GlobalContext::GetRenderAPI()->disableTests(enabledTests);
    }
    
    void RenderAPI::SubmitTriangles(
        RenderVertex*   vertices,
        const U32       vertexCount,
        U32*            indices,
        const U32       indexCount)
    {
        GlobalContext::GetRenderAPI()->submitTriangles(vertices, vertexCount, indices, indexCount);
    }

    void RenderAPI::SubmitTriangles(
        const RenderVertex2D*   vertices,
        const U32               triangleCount,
        const Matrix4f&         transform,
        const Ref<Texture>&     texture,
        const Float             tilingFactor,
        const I32               entityID)
    {
        GlobalContext::GetRenderAPI()->submitTriangles(vertices, triangleCount, transform, texture, tilingFactor, entityID);
    }

    void RenderAPI::SubmitTriangles(
        const RenderVertex3D*   vertices,
        const U32               triangleCount,
        const Matrix4f&         transform,
        const Ref<Texture>&     texture,
        const Float             tilingFactor,
        const I32               entityID)
    {
        GlobalContext::GetRenderAPI()->submitTriangles(vertices, triangleCount, transform, texture, tilingFactor, entityID);
    }

    void RenderAPI::SubmitQuads(
        const RenderVertex2D*   vertices,
        const U32               quadCount,
        const Matrix4f&         transform,
        const Ref<Texture>&     texture,
        const Float             tilingFactor,
        const I32               entityID)
    {
        GlobalContext::GetRenderAPI()->submitQuads(vertices, quadCount, transform, texture, tilingFactor, entityID);
    }

    void RenderAPI::SubmitQuads(
        const RenderVertex3D*   vertices,
        const U32               quadCount,
        const Matrix4f&         transform,
        const Ref<Texture>&     texture,
        const Float             tilingFactor,
        const I32               entityID)
    {
        GlobalContext::GetRenderAPI()->submitQuads(vertices, quadCount, transform, texture, tilingFactor, entityID);
    }
} // !namespace SE